﻿using System;
using System.Runtime.InteropServices;
using System.Text;

namespace UseDll
{
    /// <summary>
    /// 调用golang生成的dll示例代码
    /// </summary>
    internal class GoLibraryInvoke
    {
        [DllImport("golang_demo.dll", EntryPoint = "GetString", CharSet = CharSet.Unicode, CallingConvention = CallingConvention.Cdecl)]
        public static extern GoString GetString();

        [DllImport("golang_demo.dll", EntryPoint = "GetCString", CharSet = CharSet.Unicode, ExactSpelling = false)]
        public static extern IntPtr GetCString();

        [DllImport("golang_demo.dll", EntryPoint = "FreeCString", CharSet = CharSet.Unicode, ExactSpelling = false)]
        public static extern void FreeCString(IntPtr cgoString);

        /// <summary>
        /// 测试转换go语言返回的字符串到C#字符串类型
        /// <para>使用内存数据拷贝</para>
        /// </summary>
        public void GetGolangStringByMemoryCopy()
        {
            GoString goStr = GetString();
            byte[] manageArray = new byte[goStr.n];
            Marshal.Copy(goStr.p, manageArray, 0, goStr.n);
            string str = Encoding.UTF8.GetString(manageArray);
            Console.WriteLine(str);
        }

        /// <summary>
        /// 直接读取内存进行实例化
        /// </summary>
        public void GetGolangStringByDirectRead()
        {
            GoString goStr = GetString();
            unsafe
            {
                //Span<byte> memory = new Span<byte>(goStr.p.ToPointer(), goStr.n);
                string rtnValue = new string((sbyte*)goStr.p.ToPointer(), 0, goStr.n, Encoding.UTF8);
                Console.WriteLine(rtnValue);
            }
        }

        public void GetGoCString()
        {
            IntPtr data = GetCString();
            string rtnValue = Marshal.PtrToStringAnsi(data);
            Console.WriteLine(rtnValue);
            FreeCString(data);
        }
    }

    public struct GoString
    {
        public IntPtr p;
        public int n;
    }
}
